package com.suray.wcs.service.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.suray.basic.wcs.path.core.Node;
import com.suray.basic.wcs.path.core.Route;
import com.suray.basic.wcs.plc.core.Plc;
import com.suray.basic.wcs.plc.enums.PlcDeviceType;
import com.suray.basic.wcs.plc.pojo.DeviceBase;
import com.suray.basic.wcs.plc.pojo.oper.StationOper;
import com.suray.basic.wcs.plc.pojo.oper.single.DeviceInterface;
import com.suray.basic.wcs.plc.utils.PlcTaskType;
import com.suray.basic.wcs.plc.utils.PlcUnit;
import com.suray.basic.wcs.utils.Coord;
import com.suray.basic.wcs.utils.LoggerUtil;
import com.suray.basic.wcs.utils.ParamConfig;
import com.suray.basic.wcs.utils.WcsFuncUtil;
import com.suray.commin.core.utils.SpringContextHolder;
import com.suray.wcs.service.core.util.CommonUtil;
import com.suray.wcs.service.core.util.DateUtil;
import com.suray.wcs.service.core.util.SysConfigUtil;
import com.suray.wcs.service.enums.*;
import com.suray.wcs.service.plc.ConveyEvent;
import com.suray.wcs.service.pojo.BaseEum;
import com.suray.wcs.service.pojo.Rgv;
import com.suray.wcs.service.system.entity.*;
import com.suray.wcs.service.system.mapper.TaskDBMapper;
import com.suray.wcs.service.system.service.INodeDBService;
import com.suray.wcs.service.system.service.ITaskDBService;
import com.suray.wcs.service.system.service.IWareHouseDBService;
import com.suray.wcs.service.system.service.TaskDetailService;
import com.suray.wcs.service.thread.PlcTaskThread;
import com.suray.wcs.service.thread.process.PlcConveryTask;
import com.suray.wcs.service.util.WcsUtil;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;

import static com.suray.wcs.service.system.service.impl.ExceptionLogServiceImpl.INTERVAL_TIME;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author cooper
 * @since 2019-06-26
 */
@Service
public class TaskDBServiceImpl extends ServiceImpl<TaskDBMapper, TaskDB> implements ITaskDBService {
    private static Logger logger = LoggerFactory.getLogger(TaskDBServiceImpl.class);
    @Resource
    private TaskDBMapper taskdbMapper;
    @Autowired
    private INodeDBService nodeDBService;
    @Autowired
    private IWareHouseDBService IWareHouseDBService;
    @Autowired
    private TaskDetailService taskDetailService;

    /**
     * 插入数据库，触发数据库查询
     *
     * @param taskDBS
     */
    @Override
    public synchronized void insertTask(List<TaskDB> taskDBS) {
        taskDBS.forEach(taskDB -> {
            if (taskDB != null) {
                QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().eq(TaskDB::getWmsTaskId, taskDB.getWmsTaskId());
                TaskDB existTask = taskdbMapper.selectOne(queryWrapper);
                if (existTask != null) {
                    logger.info("已存在的任务，不插入任务表中");
                    return;
                }
                if (taskDB.getTaskType().equals(TaskType.CHARGE) && taskDB.getPriorityCode() == null) {
                    taskDB.setPriorityCode(1000);
                }
                if (taskDB.getPriorityCode() == null) {
                    taskDB.setPriorityCode(500);
                }
                taskDB.setTaskStatus(TaskStatus.NEW);
                if (TaskType.IN.equals(taskDB.getTaskType()) || TaskType.OUT.equals(taskDB.getTaskType())) {
                    taskDB.setPlcProgress(TaskPlcProgress.WAIT.getProgressNum());
                } else {
                    taskDB.setPlcProgress(TaskPlcProgress.ALL_DEVICE_COMPLETE.getProgressNum());
                }
                if (taskDB.getProcessingRgvNo() == null || taskDB.getProcessingRgvNo() == 0) {
                    taskDB.setRgvProgress(TaskRgvProgress.NOT_ASSIGNED_TO_RGV);
                } else {
                    taskDB.setRgvProgress(TaskRgvProgress.ASSIGNED_TO_RGV);
                    taskDB.setTaskStatus(TaskStatus.WAIT);
                }
                // 入库或者后置任务新建不分车
                if (TaskType.IN.equals(taskDB.getTaskType()) || taskDB.getPreTaskId() != null
                        || !((taskDB.getOutPortsStr() == null || taskDB.getEndNodeStr() != null))) {
                    taskDB.setAllowAssignmentRgv(false);
                } else {
                    taskDB.setAllowAssignmentRgv(true);
                }
                if (TaskType.MOVE_STATION.equals(taskDB.getTaskType())) {
                    taskDB.setPlcProgress(TaskPlcProgress.WAIT.getProgressNum());
                    taskDB.setRgvProgress(TaskRgvProgress.RGV_COMPLETE);
                    taskDB.setAllowAssignmentRgv(false);
                }
                taskDB.setOriginalEndNodeStr(taskDB.getEndNodeStr());
                if (taskDB.getTaskType() != TaskType.OUT || taskDB.selectEndNode() != null) {
                    setGroupAndZone(taskDB);
                }
                taskDB.setProcessingRgvNo(taskDB.getProcessingRgvNo());
                taskDB.setPreProcessingRgvNo(taskDB.getProcessingRgvNo());
                this.save(taskDB);
                taskDB.setPlcId(1000 + taskDB.getTaskId() % 1000);
                this.updateTaskById(taskDB);
                logger.info("插入任务 " + taskDB);
                if ((TaskType.IN.equals(taskDB.getTaskType()) && taskDB.getPreTaskId() == null) || TaskType.MOVE_STATION.equals(taskDB.getTaskType())) {
                    PlcTaskThread.getInstance(taskDB);
                }
                TaskDetailDB taskDetailDB;
                if (StringUtils.isEmpty(taskDB.getWmsTaskId())) {
                    taskDetailDB = taskDetailService.buildTask(taskDB.getTaskId(), DetailProcess.WCS_INSERT, null, taskDB.getStartNodeStr(), taskDB.getEndNodeStr(),
                            PrecessStatus.COMPLETE, null, null);
                } else {
                    taskDetailDB = taskDetailService.buildTask(taskDB.getTaskId(), DetailProcess.WMS_INSERT, null, taskDB.getStartNodeStr(), taskDB.getEndNodeStr(),
                            PrecessStatus.COMPLETE, null, null);
                }
                taskDetailService.updateTaskDetailCompleteTime(taskDetailDB);
            }
        });
    }

    /**
     * 设置出库任务终点
     * @param taskDB
     * @param endNode
     */
    public void improveTask(TaskDB taskDB, Node endNode) {
        TaskDB task = new TaskDB();
        task.setTaskId(taskDB.getTaskId());
        task.setEndNode(endNode);
        task.setTaskPortId(taskDB.getTaskPortId());
        setGroupAndZone(task);
        updateById(task);
        LoggerUtil.info("完善出库任务终点:" + task, this.getClass());
    }

    public void setGroupAndZone(TaskDB taskdb) {
        NodeDB node;
        WareHouseDB wcsDistrictDB = IWareHouseDBService.getCurWareHouseDB();
        if (TaskType.OUT.equals(taskdb.getTaskType())) {
            node = nodeDBService.getNodeDB(taskdb.selectStartNode());
            setGroupIdAndSingleRgvFlag(node, wcsDistrictDB, taskdb);
            node = nodeDBService.getNodeDB(taskdb.selectEndNode());
            setNodeLimitRgvFlag(node, taskdb);
        } else if (TaskType.IN.equals(taskdb.getTaskType())) {
            node = nodeDBService.getNodeDB(taskdb.selectEndNode());
            setGroupIdAndSingleRgvFlag(node, wcsDistrictDB, taskdb);
            node = nodeDBService.getNodeDB(taskdb.selectStartNode());
            setNodeLimitRgvFlag(node, taskdb);
        } else if (TaskType.TRANSFER.equals(taskdb.getTaskType())) {
            node = nodeDBService.getNodeDB(taskdb.selectStartNode());
            if (node != null) {
                taskdb.setGroupId(node.getRoadNo());
                if (wcsDistrictDB.getSingleRgvFlag()) {
                    taskdb.setSingleRgvFlag(node.getRoadNo());
                }
                if (node.getLimitRgvCount() != null) {
                    taskdb.setNodeLimitRgvFlag(node.getNodeId());
                }
            }
            node = nodeDBService.getNodeDB(taskdb.selectEndNode());
            if (node != null) {
                if (wcsDistrictDB.getSingleRgvFlag()) {
                    taskdb.setGroupIdSecond(node.getRoadNo());
                }
                if (node.getLimitRgvCount() != null) {
                    taskdb.setTransEndNodeLimitRgvFlag(node.getNodeId());
                }
            }
        }

        node = nodeDBService.getNodeDB(taskdb.selectEndNode());
        if (node != null) {
            taskdb.setZoneId(node.getZoneId());
        }

    }

    private void setNodeLimitRgvFlag(NodeDB node, TaskDB taskdb) {
        if (node != null) {
            if (node.getLimitRgvCount() != null) {
                taskdb.setNodeLimitRgvFlag(node.getNodeId());
            }
        }
    }

    private void setGroupIdAndSingleRgvFlag(NodeDB node, WareHouseDB wcsDistrictDB, TaskDB taskdb) {
        if (node != null) {
            taskdb.setGroupId(node.getRoadNo());
            if (wcsDistrictDB.getSingleRgvFlag()) {
                taskdb.setSingleRgvFlag(node.getRoadNo());
            }
        }
    }

    /**
     * 更新任务执行小车
     *
     * @param rgv
     * @param task
     */
    @Override
    public synchronized void updateTaskProcessingRgv(Rgv rgv, TaskDB task) {
        task.setProcessingRgvNo(rgv.getRgvDB().getRgvNo());
        TaskDB currentTask = new TaskDB();
        currentTask.setTaskId(task.getTaskId());
        currentTask.setProcessingRgvNo(rgv.getRgvDB().getRgvNo());
        this.updateTaskById(currentTask);
        logger.info("给任务" + task + "分配小车--->" + rgv);
    }

    /**
     * 更新任务预执行小车
     *
     * @param rgv
     * @param task
     */
    @Override
    public synchronized void updateTaskPreProcessingRgv(Rgv rgv, TaskDB task) {
        task.setPreProcessingRgvNo(rgv.getRgvDB().getRgvNo());
        TaskDB currentTask = new TaskDB();
        currentTask.setTaskId(task.getTaskId());
        currentTask.setPreProcessingRgvNo(rgv.getRgvDB().getRgvNo());
        this.updateTaskById(currentTask);
        logger.info("任务" + task + "重新预分配小车--->" + rgv);
    }

    /**
     * 更新任务执行小车
     *
     * @param rgv
     * @param task
     */
    @Override
    public void updateTaskProcessingRgvAndTaskRgvProgress(Rgv rgv, TaskDB task, TaskStatus taskStatus, TaskRgvProgress taskRgvProgress) {
        task.setProcessingRgvNo(rgv.getRgvDB().getRgvNo());
        task.setRgvProgress(taskRgvProgress);
        task.setTaskStatus(taskStatus);
        TaskDB currentTask = new TaskDB();
        currentTask.setTaskId(task.getTaskId());
        currentTask.setProcessingRgvNo(rgv.getRgvDB().getRgvNo());
        currentTask.setRgvProgress(taskRgvProgress);
        currentTask.setTaskStatus(taskStatus);
        this.updateTaskByIdAndType(currentTask, 0);
        TaskDetailDB taskDetailDB = taskDetailService.getTaskDetail(task.getTaskId(), DetailProcess.FORMAL_ASSIGN, null, null, null,
                PrecessStatus.CONDUCT, rgv.getRgvDB().getRgvNo().toString(), null);
        taskDetailService.updateTaskDetailCompleteTime(taskDetailDB);
        logger.info("给任务" + task + "分配小车--->" + rgv);
    }

    /**
     * 更新小车任务进度
     *
     * @param task
     * @param taskRgvProgress
     */
    @Override
    public synchronized boolean updateTaskRgvProgress(TaskDB task, TaskRgvProgress taskRgvProgress) {
        task.setRgvProgress(taskRgvProgress);
        TaskDB currentTask = new TaskDB();
        currentTask.setTaskId(task.getTaskId());
        currentTask.setRgvProgress(taskRgvProgress);
        boolean result = this.updateTaskById(currentTask);
        logger.info("更新了小车任务进度->" + taskRgvProgress + "结果：" + result);
        return result;
    }

    /**
     * 查询分配给当前车的第一个任务
     */
    @Override
    public synchronized TaskDB findFirstCanExecuteTask(Integer rgvNo) {
        LambdaQueryWrapper<TaskDB> eq = new QueryWrapper<TaskDB>().lambda().eq(TaskDB::getProcessingRgvNo, rgvNo)
                .ne(TaskDB::getRgvProgress, TaskRgvProgress.RGV_COMPLETE)
                .ne(TaskDB::getTaskType, TaskType.RUN_FOR_GCODE)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL).orderByDesc(TaskDB::getPriorityCode).orderByAsc(TaskDB::getTaskId);
        List<TaskDB> newTasks = this.list(eq);
        if (newTasks != null && newTasks.size() != 0) {
            return newTasks.get(0);
        }
        return null;
    }

    /**
     * 查询分配给当前车的第一个任务
     */
    @Override
    public synchronized TaskDB findFirstCanExecuteTaskByTaskType(Integer rgvNo, TaskType taskType) {
        LambdaQueryWrapper<TaskDB> eq = new QueryWrapper<TaskDB>().lambda().eq(TaskDB::getProcessingRgvNo, rgvNo)
                .eq(TaskDB::getTaskType, taskType)
                .ne(TaskDB::getRgvProgress, TaskRgvProgress.RGV_COMPLETE)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                .orderByDesc(TaskDB::getPriorityCode).orderByAsc(TaskDB::getTaskId);
        List<TaskDB> newTasks = this.list(eq);
        if (newTasks != null && newTasks.size() != 0) {
            return newTasks.get(0);
        }
        return null;
    }

    /**
     * 查询分配给当前车可执行的第一个任务
     */
    @Override
    public synchronized TaskDB findFirstCanExecuteTaskForPreAssignAdjustOrAssigned(Integer rgvNo) {
        TaskDB taskDB = findFirstCanExecuteTask(rgvNo);
        if (taskDB == null) {
            return null;
        }
        if (SysConfigUtil.PRE_ASSIGN_ADJUST) {
            return taskDB;
        } else {
            TaskDB bestTaskDB = getPriorityTask(taskDB, rgvNo);
            return bestTaskDB;
        }
    }

    private TaskDB getPriorityTask(TaskDB taskDB, Integer rgvNo) {
        // 入库优先
        if (PriorityMode.IN.getValue().equals(IWareHouseDBService.getPriorityMode())) {
            return getPriorityModeTask(taskDB, rgvNo, TaskType.IN);
        } else if (PriorityMode.OUT.getValue().equals(IWareHouseDBService.getPriorityMode())) {
            return getPriorityModeTask(taskDB, rgvNo, TaskType.OUT);
        } else if (PriorityMode.BALANCE.getValue().equals(IWareHouseDBService.getPriorityMode())) {
            if (TaskType.IN.equals(taskDB.getTaskType())) {
                return getPriorityModeTask(taskDB, rgvNo, TaskType.OUT);
            } else if (TaskType.OUT.equals(taskDB.getTaskType())) {
                return getPriorityModeTask(taskDB, rgvNo, TaskType.IN);
            } else {
                return taskDB;
            }
        } else if (PriorityMode.PRIORITY_INSERT_TIME.getValue().equals(IWareHouseDBService.getPriorityMode())) {
            return taskDB;
        } else {
            return taskDB;
        }
    }

    private TaskDB getPriorityModeTask(TaskDB taskDB, Integer rgvNo, TaskType taskType) {
        // 如果是移库、充电、空载、载货、避让、避让状态任务，则按优先级降序加插入时间升序优先执行
        if (TaskType.TRANSFER == taskDB.getTaskType() || TaskType.CHARGE == taskDB.getTaskType() || TaskType.MOVE_UNLOADED == taskDB.getTaskType()
                || TaskType.MOVE_LOADED == taskDB.getTaskType() || CommonUtil.PRIORITY_CODE_AVOID.equals(taskDB.getPriorityCode())
                || CommonUtil.PRIORITY_CODE_ERROR.equals(taskDB.getPriorityCode())) {
            return taskDB;
        }
        TaskDB priorityTaskDB = findFirstCanExecuteTaskByTaskType(rgvNo, taskType);
        if (priorityTaskDB != null) {
            return priorityTaskDB;
        } else {
            return taskDB;
        }
    }

    /**
     * 查询分配给当前车的第一个任务
     *
     * @param rgvNo
     * @return
     */
    @Override
    public synchronized List<TaskDB> findCanExecuteTaskList(Integer rgvNo) {
        LambdaQueryWrapper<TaskDB> eq = new QueryWrapper<TaskDB>().lambda().eq(TaskDB::getProcessingRgvNo, rgvNo)
                .ne(TaskDB::getRgvProgress, TaskRgvProgress.RGV_COMPLETE)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH)
                .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .orderByDesc(TaskDB::getPriorityCode).orderByAsc(TaskDB::getTaskId);
        return this.list(eq);
    }


    /**
     * 查找未车辆执行进度为前往起点中，且不为取消的出入移库任务，且是wms下发的任务，且有预分车的任务
     *
     * @param rgvNo
     * @return
     */
    @Override
    public synchronized List<TaskDB> findCanReAssignTaskList(Integer rgvNo) {
        LambdaQueryWrapper<TaskDB> eq = new QueryWrapper<TaskDB>().lambda().eq(TaskDB::getProcessingRgvNo, rgvNo)
                .ne(TaskDB::getRgvProgress, TaskRgvProgress.RGV_COMPLETE)
                .ne(TaskDB::getRgvProgress, TaskRgvProgress.RGV_TO_END)
                .in(TaskDB::getTaskType, Arrays.asList(TaskType.IN, TaskType.OUT, TaskType.TRANSFER))
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                .isNotNull(TaskDB::getPreProcessingRgvNo)
                .isNotNull(TaskDB::getWmsTaskId)
                .orderByDesc(TaskDB::getPriorityCode).orderByAsc(TaskDB::getTaskId);
        return this.list(eq);
    }

    /**
     * 查询分配以及预分配给当前车的任务
     */
    @Override
    public synchronized List<TaskDB> findTaskListByRgvNo(Integer rgvNo) {
        QueryWrapper<TaskDB> eq = new QueryWrapper<TaskDB>();
        eq.and(wrapper -> wrapper.lambda().eq(TaskDB::getProcessingRgvNo, rgvNo).or((qw -> qw.eq(TaskDB::getPreProcessingRgvNo, rgvNo).isNull(TaskDB::getProcessingRgvNo))));
        eq.lambda().ne(TaskDB::getRgvProgress, TaskRgvProgress.RGV_COMPLETE)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH);
        return this.list(eq);
    }

    /**
     * 查询分配以及预分配给当前车的任务
     */
    @Override
    public synchronized List<TaskDB> findTaskListByRgvNoAndZoneId(Integer rgvNo, Integer zoneId) {
        QueryWrapper<TaskDB> eq = new QueryWrapper<TaskDB>();
        eq.and(wrapper -> wrapper.lambda().eq(TaskDB::getProcessingRgvNo, rgvNo).or((qw -> qw.eq(TaskDB::getPreProcessingRgvNo, rgvNo).isNull(TaskDB::getProcessingRgvNo))));
        eq.lambda().ne(TaskDB::getRgvProgress, TaskRgvProgress.RGV_COMPLETE)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH);
        if (zoneId != null) {
            eq.lambda().eq(TaskDB::getZoneId, zoneId);
        } else {
            eq.lambda().isNull(TaskDB::getZoneId);
        }
        return this.list(eq);
    }

    /**
     * 判断是否已分配以及预分配任务
     */
    @Override
    public boolean existUnFinishTask(Rgv rgv) {
        List<TaskDB> taskDBList = this.findTaskListByRgvNo(rgv.getRgvDB().getRgvNo());
        if (CollectionUtils.isNotEmpty(taskDBList)) {
            return true;
        }
        return false;
    }

    /**
     * 查询预分配任务
     */
    @Override
    public synchronized List<TaskDB> findPreAndAssignTaskList(Integer rgvNo) {
        QueryWrapper<TaskDB> eq = new QueryWrapper<TaskDB>();
        eq.and(wrapper -> wrapper.lambda().eq(TaskDB::getProcessingRgvNo, rgvNo).or(qw -> qw.eq(TaskDB::getPreProcessingRgvNo, rgvNo).isNull(TaskDB::getProcessingRgvNo)));
        eq.lambda().ne(TaskDB::getRgvProgress, TaskRgvProgress.RGV_COMPLETE)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL).ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH).orderByDesc(TaskDB::getPriorityCode).orderByAsc(TaskDB::getTaskId);
        return this.list(eq);
    }

    /**
     * 查询预分配任务
     */
    @Override
    public synchronized TaskDB findLastPreAndAssignTaskList(Integer rgvNo) {
        QueryWrapper<TaskDB> eq = new QueryWrapper<TaskDB>();
        eq.and(wrapper -> wrapper.lambda().eq(TaskDB::getProcessingRgvNo, rgvNo).or(qw -> qw.eq(TaskDB::getPreProcessingRgvNo, rgvNo).isNull(TaskDB::getProcessingRgvNo)));
        eq.lambda().ne(TaskDB::getRgvProgress, TaskRgvProgress.RGV_COMPLETE)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL).ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH).orderByAsc(TaskDB::getPriorityCode).orderByDesc(TaskDB::getTaskId);
        List<TaskDB> newTasks = this.list(eq);
        if (newTasks != null && newTasks.size() != 0) {
            return newTasks.get(0);
        }
        return null;
    }

    /**
     * 查询小车当前预分车的任务
     */
    @Override
    public synchronized List<TaskDB> findPreTaskList(Integer rgvNo) {
        LambdaQueryWrapper<TaskDB> eq = new QueryWrapper<TaskDB>().lambda().eq(TaskDB::getPreProcessingRgvNo, rgvNo)
                .isNull(TaskDB::getProcessingRgvNo).ne(TaskDB::getRgvProgress, TaskRgvProgress.RGV_COMPLETE)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL).ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH).orderByDesc(TaskDB::getPriorityCode).orderByAsc(TaskDB::getTaskId);
        return this.list(eq);
    }

    /**
     * 查询小车当前层预分配任务
     */
    @Override
    public synchronized List<TaskDB> findCurrentFloorPreTaskList(Integer rgvNo, int floor) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<TaskDB>();
        queryWrapper.and(wrapper -> wrapper.lambda().like(TaskDB::getStartNodeStr, floor + ")").or().like(TaskDB::getEndNodeStr, floor + ")"));
        queryWrapper.lambda().eq(TaskDB::getPreProcessingRgvNo, rgvNo)
                .isNull(TaskDB::getProcessingRgvNo)
                .ne(TaskDB::getRgvProgress, TaskRgvProgress.RGV_COMPLETE)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL).ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH);
        return this.list(queryWrapper);
    }

    /**
     * 指定任务类型查询预分配任务
     */
    @Override
    public synchronized List<TaskDB> findPreTaskListByTaskType(Integer rgvNo, TaskType taskType) {
        LambdaQueryWrapper<TaskDB> eq = new QueryWrapper<TaskDB>().lambda().eq(TaskDB::getPreProcessingRgvNo, rgvNo)
                .isNull(TaskDB::getProcessingRgvNo)
                .eq(TaskDB::getTaskType, taskType)
                .ne(TaskDB::getRgvProgress, TaskRgvProgress.RGV_COMPLETE)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH)
                .orderByDesc(TaskDB::getPriorityCode).orderByAsc(TaskDB::getTaskId);
        return this.list(eq);
    }

    /**
     * 查询分配给当前车的最后一个任务
     */
    @Override
    public synchronized TaskDB findLastCanExecuteTask(Integer rgvNo) {
        LambdaQueryWrapper<TaskDB> eq = new QueryWrapper<TaskDB>().lambda().eq(TaskDB::getProcessingRgvNo, rgvNo)
                .ne(TaskDB::getRgvProgress, TaskRgvProgress.RGV_COMPLETE)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL).orderByAsc(TaskDB::getPriorityCode).orderByDesc(TaskDB::getTaskId);
        List<TaskDB> newTasks = this.list(eq);
        if (newTasks != null && newTasks.size() != 0) {
            return newTasks.get(0);
        }
        return null;
    }

    /**
     * 更新设备任务进度
     *
     * @param task
     * @param taskProgress
     */
    @Override
    public synchronized void updateTaskPlcProgressAndTaskStatus(TaskDB task, int taskProgress, TaskStatus taskStatus) {
        task.setPlcProgress(taskProgress);
        task.setTaskStatus(taskStatus);
        TaskDB currentTask = new TaskDB();
        currentTask.setTaskId(task.getTaskId());
        currentTask.setPlcProgress(taskProgress);
        currentTask.setTaskStatus(taskStatus);
        this.updateTaskById(currentTask);
        logger.info("更新了任务PLC进度->" + taskProgress);
    }

    /**
     * 更新设备任务进度
     *
     * @param task
     * @param taskProgress
     */
    @Override
    public synchronized void updateTaskPlcProgress(TaskDB task, int taskProgress) {
        task.setPlcProgress(taskProgress);
        TaskDB currentTask = new TaskDB();
        currentTask.setTaskId(task.getTaskId());
        currentTask.setPlcProgress(taskProgress);
        this.updateTaskById(currentTask);
        logger.info("更新了任务PLC进度->" + taskProgress);
    }

    /**
     * 获取新插入数据库的任务
     *
     * @return
     */
    @Override
    public List<TaskDB> findAllNewTask() {
        List<TaskDB> newTasks = this.list(new QueryWrapper<TaskDB>().lambda().eq(TaskDB::getTaskStatus, TaskStatus.NEW)
                .isNull(TaskDB::getProcessingRgvNo).isNull(TaskDB::getPreProcessingRgvNo));
        return newTasks;
    }

    /**
     * 预分配车辆为空&&执行车辆为空&&达到分车条件
     * 还未进行预分配
     *
     * @return
     */
    @Override
    public List<TaskDB> getPreProcessingRgvNoIsNull() {
        LambdaQueryWrapper<TaskDB> lambdaQueryWrapper = new LambdaQueryWrapper();
        lambdaQueryWrapper.isNull(TaskDB::getPreProcessingRgvNo).isNull(TaskDB::getProcessingRgvNo)
                .isNotNull(TaskDB::getEndNodeStr)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL).ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH)
                .eq(TaskDB::getAllowAssignmentRgv, true).orderByDesc(TaskDB::getPriorityCode).orderByAsc(TaskDB::getTaskId);
        return list(lambdaQueryWrapper);
    }

    /**
     * 出库终点未分配任务
     *
     * @return
     */
    @Override
    public List<TaskDB> getNoEndNodeTask() {
        LambdaQueryWrapper<TaskDB> lambdaQueryWrapper = new LambdaQueryWrapper();
        lambdaQueryWrapper.isNull(TaskDB::getEndNodeStr).isNotNull(TaskDB::getStartNodeStr)
                .isNotNull(TaskDB::getWmsTaskId)
                .isNotNull(TaskDB::getOutPortsStr)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL).ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH)
                .eq(TaskDB::getTaskType, TaskType.OUT)
                .orderByDesc(TaskDB::getPriorityCode).orderByAsc(TaskDB::getTaskId);
        return list(lambdaQueryWrapper);
    }

    /**
     * 获取没有分配车的任务
     *
     * @return
     */
    @Override
    public List<TaskDB> getNotAssignmentTask() {
        List<TaskDB> notAssignmentTasks = this.list(new QueryWrapper<TaskDB>().lambda().isNull(TaskDB::getProcessingRgvNo));
        return notAssignmentTasks;
    }

    @Override
    public int countByProcessingRgvNo(int rgvNo) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.and(wrapper -> wrapper.lambda().eq(TaskDB::getProcessingRgvNo, rgvNo).or((qw -> qw.eq(TaskDB::getPreProcessingRgvNo, rgvNo).isNull(TaskDB::getProcessingRgvNo))));
        queryWrapper.lambda().eq(TaskDB::getPreProcessingRgvNo, rgvNo)
                .ne(TaskDB::getRgvProgress, TaskRgvProgress.RGV_COMPLETE)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH);
        List<TaskDB> newTasks = this.list(queryWrapper);
        if (newTasks != null && newTasks.size() != 0) {
            return newTasks.size();
        }
        return 0;
    }

    /**
     * 获取所有需要一键恢复的任务
     *
     * @return
     */
    @Override
    public List<TaskDB> getRecoverAllNewTask() {
        List<TaskDB> newTasks = this.list(new QueryWrapper<TaskDB>().lambda().eq(TaskDB::getTaskStatus, TaskStatus.NEW.getProgressNum())
                .or().eq(TaskDB::getTaskStatus, TaskStatus.WAIT.getProgressNum()));
        return newTasks;
    }


    /**
     * 清空任务
     *
     * @return
     */
    @Override
    public int deleteTask() {
        return taskdbMapper.delete(null);
    }

    /**
     * 删除多条任务
     *
     * @param taskDBS
     * @return
     */
    @Override
    public int deleteTask(List<TaskDB> taskDBS) {
        return taskdbMapper.deleteTasks(taskDBS);
    }

    /**
     * 查询所有任务
     *
     * @param taskInfo
     * @return
     */
    @Override
    public List<TaskDB> queryTaskInfo(TaskDB taskInfo) {
        return taskdbMapper.queryTaskInfo(taskInfo);
    }

    @Override
    public List<TaskDB> queryTasks(TaskDB taskDB) {

        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper();
        if (!StringUtils.isEmpty(taskDB.getWmsTaskId())) {
            queryWrapper.lambda().like(TaskDB::getWmsTaskId, taskDB.getWmsTaskId());
        }
        if (!StringUtils.isEmpty(taskDB.getTaskId())) {
            queryWrapper.lambda().like(TaskDB::getTaskId, taskDB.getTaskId());
        }
        if (taskDB.getTaskType() != null) {
            queryWrapper.lambda().eq(TaskDB::getTaskType, taskDB.getTaskType());
        }
        if (taskDB.getProcessingRgvNo() != null) {
            queryWrapper.lambda().eq(TaskDB::getProcessingRgvNo, taskDB.getProcessingRgvNo().intValue());
        }
        if (taskDB.getTaskStatus() != null) {
            queryWrapper.lambda().eq(TaskDB::getTaskStatus, taskDB.getTaskStatus());
        }
        if (taskDB.getPlcProgress() != null) {
            queryWrapper.lambda().eq(TaskDB::getPlcProgress, taskDB.getPlcProgress().intValue());
        }
        if (taskDB.getRgvProgress() != null) {
            queryWrapper.lambda().eq(TaskDB::getRgvProgress, taskDB.getRgvProgress());
        }
        if (taskDB.getTaskType() != null) {
            queryWrapper.lambda().eq(TaskDB::getTaskType, taskDB.getTaskType());
        }
        if (!StringUtils.isEmpty(taskDB.getBarCode())) {
            queryWrapper.lambda().like(TaskDB::getBarCode, taskDB.getBarCode());
        }
        if (!StringUtils.isEmpty(taskDB.getTaskPortId())) {
            queryWrapper.lambda().like(TaskDB::getTaskPortId, taskDB.getTaskPortId());
        }
        if (!StringUtils.isEmpty(taskDB.getStartNodeStr())) {
            queryWrapper.lambda().like(TaskDB::getStartNodeStr, taskDB.getStartNodeStr());
        }
        if (!StringUtils.isEmpty(taskDB.getEndNodeStr())) {
            queryWrapper.lambda().like(TaskDB::getEndNodeStr, taskDB.getEndNodeStr());
        }
        if (!StringUtils.isEmpty(taskDB.getParams().get("beginTime"))) {
            queryWrapper.lambda().ge(TaskDB::getCreateTime, taskDB.getParams().get("beginTime"));
        }
        if (!StringUtils.isEmpty(taskDB.getParams().get("endTime"))) {
            queryWrapper.lambda().le(TaskDB::getCreateTime, taskDB.getParams().get("endTime"));
        }
        if (taskDB.getTaskStatusGroup() != null) {
            if (taskDB.getTaskStatusGroup() == TaskStatusGroup.UN_FINISH.getProgressNum()) {
                queryWrapper.and(Wrapper -> Wrapper.and(ww -> ww.lambda().ne(TaskDB::getTaskStatus, TaskStatus.FINISH.getProgressNum())
                        .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED.getProgressNum())
                        .isNull(TaskDB::getWmsTaskId))
                        .or().ne("plc_progress", TaskPlcProgress.ALL_DEVICE_COMPLETE.getProgressNum())
                        .or().ne("rgv_progress", TaskRgvProgress.RGV_COMPLETE.getProgressNum())
                        .or(ww -> ww.lambda().ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED.getProgressNum())
                                .isNotNull(TaskDB::getWmsTaskId))
                );
            } else if (taskDB.getTaskStatusGroup() == TaskStatusGroup.ERROR.getProgressNum()) {
                queryWrapper.lambda().eq(TaskDB::getTaskStatus, TaskStatus.ERROR.getProgressNum());
            } else if (taskDB.getTaskStatusGroup() == TaskStatusGroup.CANCEL.getProgressNum()) {
                queryWrapper.lambda().eq(TaskDB::getTaskStatus, TaskStatus.CANCEL.getProgressNum());
            } else {
                queryWrapper.lambda().and(ww -> ww.eq(TaskDB::getTaskStatus, TaskStatus.FINISH.getProgressNum()).or().
                        eq(TaskDB::getTaskStatus, TaskStatus.COMMITTED.getProgressNum()))
                        .eq(TaskDB::getPlcProgress, TaskPlcProgress.ALL_DEVICE_COMPLETE.getProgressNum())
                        .eq(TaskDB::getRgvProgress, TaskRgvProgress.RGV_COMPLETE.getProgressNum());
            }
        }
        queryWrapper.orderByDesc("create_time");
        return taskdbMapper.selectList(queryWrapper);
    }


    /**
     * 根据Id查询任务
     *
     * @param taskId
     * @return
     */
    @Override
    public TaskDB queryTaskInfoById(Integer taskId) {
        return taskdbMapper.selectById(taskId);
    }

    /**
     * 根据wmsId查询任务
     *
     * @param wmsTaskId
     * @return
     */
    @Override
    public TaskDB queryTaskInfoByWMSId(String wmsTaskId) {
        List<TaskDB> newTasks = this.list(new QueryWrapper<TaskDB>().lambda().eq(TaskDB::getWmsTaskId, wmsTaskId));
        if (newTasks == null || newTasks.size() == 0) {
            return null;
        }
        return newTasks.get(0);
    }

    /**
     * 设置优先
     *
     * @param task 当前任务
     */
    @Override
    public void updateSortCode(TaskDB task) {
        task.setPriorityCode(task.getPriorityCode());
        TaskDB currentTask = new TaskDB();
        currentTask.setTaskId(task.getTaskId());
        currentTask.setPriorityCode(task.getPriorityCode());
        this.updateById(currentTask);
    }

    /**
     * 更新设备任务进度
     *
     * @param task
     * @param taskProgress
     */
    @Override
    public synchronized boolean updateTaskStatus(TaskDB task, TaskStatus taskProgress) {
        task.setTaskStatus(taskProgress);
        TaskDB currentTask = new TaskDB();
        currentTask.setTaskId(task.getTaskId());
        if (taskProgress.getProgressNum() == TaskStatus.ON_GOING.getProgressNum()) {
            Date date = new Date();
            currentTask.setExecuteTime(date);
            task.setExecuteTime(date);
        }
        if (taskProgress.getProgressNum() == TaskStatus.FINISH.getProgressNum()) {
            currentTask.setCompleteTime(new Date());
            //添加耗时字段
            if (task.getExecuteTime() != null) {
                //添加耗时字段
                Long executeTime = task.getExecuteTime().getTime();
                Long completeTime = currentTask.getCompleteTime().getTime();
                Long timeConsuming = (completeTime - executeTime) / 1000;
                currentTask.setTimeConsuming(timeConsuming + "");
            }
        }

        if (taskProgress.getProgressNum() == TaskStatus.COMMITTED.getProgressNum()) {
            currentTask.setRemark("");
            currentTask.setCommitTime(new Date());
        } else {
            currentTask.setCommitTime(null);
        }
        if (taskProgress.getProgressNum() == TaskStatus.CANCEL.getProgressNum()
                || taskProgress.getProgressNum() == TaskStatus.FINISH.getProgressNum()
                || taskProgress.getProgressNum() == TaskStatus.COMMITTED.getProgressNum()) {
            String value = Plc.PLC_INTERRUPT_CACHE.get(String.valueOf(task.getTaskId()));
            if (!StringUtils.isEmpty(value)) {
                Plc.PLC_INTERRUPT_CACHE.remove(String.valueOf(task.getTaskId()));
            }
        }
        currentTask.setTaskStatus(taskProgress);
        boolean result = this.updateTaskById(currentTask);
        logger.info("更新了任务号:" + task.getTaskId() + "的任务进度->" + taskProgress);
        return result;
    }

    /**
     * 更新任务异常提示信息
     *
     * @param task
     */
    @Override
    public synchronized boolean updateTaskTips(TaskDB task, String tips) {
        TaskDB currentTask = new TaskDB();
        currentTask.setTaskId(task.getTaskId());
        if (tips != null) {
            currentTask.setTips(tips);
        }
        boolean result = this.updateTaskById(currentTask);
        logger.info("更新了任务号:" + task.getTaskId() + "的任务提示->" + tips);
        return result;
    }

    @Override
    public void deleteTaskForDays(Integer days) {
        taskdbMapper.deleteTaskForDays(days);
    }

    @Override
    public void deleteManualTaskForDays(Integer days) {
        List<TaskDB> taskDBS = taskdbMapper.queryTaskForDays(days);
        List<TaskDB> taskDBList = new ArrayList<>();
        for (TaskDB taskDB : taskDBS) {
            if ((taskDB.getTaskType() == TaskType.CHARGE || taskDB.getTaskType() == TaskType.MOVE_LOADED ||
                    taskDB.getTaskType() == TaskType.MOVE_UNLOADED) && taskDB.getTaskStatus() == TaskStatus.FINISH) {
                taskDBList.add(taskDB);
            }
        }
        taskdbMapper.deleteTasks(taskDBList);
    }

    @Override
    public List<TaskDB> queryTaskForDays(Integer days) {
        return taskdbMapper.queryTaskForDays(days);
    }

    @Override
    public List<TaskDB> queryManualTaskForDays(Integer days) {
        List<TaskDB> taskDBS = taskdbMapper.queryTaskForDays(days);
        List<TaskDB> taskDBList = new ArrayList<>();
        for (TaskDB taskDB : taskDBS) {
            if ((taskDB.getTaskType() == TaskType.CHARGE || taskDB.getTaskType() == TaskType.MOVE_LOADED ||
                    taskDB.getTaskType() == TaskType.MOVE_UNLOADED) && taskDB.getTaskStatus() == TaskStatus.FINISH) {
                taskDBList.add(taskDB);
            }
        }
        return taskDBList;
    }

    /**
     * 更新任务
     *
     * @param taskdb
     * @return
     */
    @Override
    public int updateTaskInfo(TaskDB taskdb) {
        return taskdbMapper.updateById(taskdb);
    }

    /**
     * 更新任务
     *
     * @param taskdb
     * @return
     */
    @Override
    public int updateTaskInfoAllowNull(TaskDB taskdb) {
        LambdaUpdateWrapper<TaskDB> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(TaskDB::getTaskStatus, taskdb.getTaskStatus())
                .set(TaskDB::getRgvProgress, taskdb.getRgvProgress())
                .set(TaskDB::getPlcProgress, taskdb.getPlcProgress())
                .set(TaskDB::getProcessingRgvNo, taskdb.getProcessingRgvNo())
                .set(TaskDB::getPriorityCode, taskdb.getPriorityCode());
        updateWrapper.set(TaskDB::getCommitTime, taskdb.getCommitTime());
        updateWrapper.eq(TaskDB::getTaskId, taskdb.getTaskId());

        return taskdbMapper.update(null, updateWrapper);
    }

    /**
     * 查询任务类型枚举下拉框数据
     *
     * @return
     */
    @Override
    public List<BaseEum> queryTaskType() {
        List<TaskType> taskManagerType = (Arrays.asList(TaskType.values()));
        List<BaseEum> taskTypeList = new ArrayList<BaseEum>();
        //移除载货行驶
        for (TaskType taskType : taskManagerType) {
            if (taskType != TaskType.MOVE_LOADED) {
                taskTypeList.add(new BaseEum(taskType.getTypeNum(), taskType.toString()));
            }
        }
        return taskTypeList;
    }

    /**
     * 查询任务状态枚举下拉框数据
     *
     * @return
     */
    @Override
    public List<BaseEum> queryTaskStatus() {
        List<TaskStatus> taskManagerType = (Arrays.asList(TaskStatus.values()));
        List<BaseEum> taskTypeList = new ArrayList<BaseEum>();
        for (TaskStatus taskType : taskManagerType) {
            taskTypeList.add(new BaseEum(taskType.getProgressNum(), taskType.toString()));
        }
        return taskTypeList;
    }

    /**
     * 查询任务状态枚举下拉框数据
     *
     * @return
     */
    @Override
    public List<BaseEum> queryTaskStatusGroup() {
        List<TaskStatusGroup> taskStatusGroups = (Arrays.asList(TaskStatusGroup.values()));
        List<BaseEum> taskTypeList = new ArrayList<BaseEum>();
        for (TaskStatusGroup item : taskStatusGroups) {
            taskTypeList.add(new BaseEum(item.getProgressNum(), item.toString()));
        }
        return taskTypeList;
    }

    /**
     * 查询任务状态枚举下拉框数据
     *
     * @return
     */
    @Override
    public List<BaseEum> queryTaskProgress() {
        List<TaskPlcProgress> taskManagerProgress = (Arrays.asList(TaskPlcProgress.values()));
        List<BaseEum> taskTypeList = new ArrayList<BaseEum>();
        for (TaskPlcProgress taskType : taskManagerProgress) {
            if (taskType.getProgressNum() == TaskPlcProgress.WAIT.getProgressNum() || taskType.getProgressNum() == TaskPlcProgress.ALL_DEVICE_COMPLETE.getProgressNum()) {
                taskTypeList.add(new BaseEum(taskType.getProgressNum(), taskType.toString()));
            }
        }
        return taskTypeList;
    }

    /**
     * 查询任务小车进度下拉框数据
     *
     * @return
     */
    @Override
    public List<BaseEum> queryTaskRgvProgress() {
        List<TaskRgvProgress> taskManagerRgvProgress = (Arrays.asList(TaskRgvProgress.values()));
        List<BaseEum> taskTypeList = new ArrayList<BaseEum>();
        for (TaskRgvProgress taskType : taskManagerRgvProgress) {
            taskTypeList.add(new BaseEum(taskType.getProgressNum(), taskType.toString()));
        }
        return taskTypeList;
    }

    /**
     * 寻找未完成的出库任务数
     *
     * @return
     */
    @Override
    public int findUnFinishOutTask() {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().lt(TaskDB::getTaskStatus, TaskStatus.FINISH).eq(TaskDB::getTaskType, TaskType.OUT);
        List<TaskDB> taskDBS = taskdbMapper.selectList(queryWrapper);
        if (taskDBS == null || taskDBS.size() == 0) {
            return 0;
        }
        return taskDBS.size();
    }

    /**
     * 查询所有未完成的任务
     *
     * @return
     */
    @Override
    public List<TaskDB> findAllUnFinishTask(TaskType taskType) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        if (taskType != null) {
            queryWrapper.lambda().eq(TaskDB::getTaskType, taskType);
        }
        queryWrapper.lambda().lt(TaskDB::getTaskStatus, TaskStatus.FINISH).or().eq(TaskDB::getTaskStatus, TaskStatus.ERROR).or().eq(TaskDB::getTaskStatus, TaskStatus.AVOID);

        List<TaskDB> taskDBS = taskdbMapper.selectList(queryWrapper);
        return taskDBS;
    }

    /**
     * 更新任务执行状态时更新执行时间至当前时间
     *
     * @param taskdb
     * @return 更新成功与否
     * @author rbj
     */
    @Override
    public boolean updateTaskById(TaskDB taskdb) {
        return this.updateById(taskdb);
    }

    @Override
    public synchronized boolean updateTaskByIdAndType(TaskDB taskdb, Integer type) {
        if (0 == type) {
            TaskDB newTaskDB = this.getTaskDBById(taskdb.getTaskId());
            if (newTaskDB.getProcessingRgvNo() == null) {
                return this.updateById(taskdb);
            }
            return true;
        } else {
            return this.updateById(taskdb);
        }
    }


    /**
     * 运行输送线任务
     *
     * @param start
     * @param end
     */
    @Override
    public void runStation(Node start, Node end, PlcTaskType plcTaskType) {
        DeviceBase startStation = Plc.deviceStationCoordMap.get(new Coord(start));
        DeviceBase endStation = Plc.deviceStationCoordMap.get(new Coord(end));

        if (plcTaskType != null) {
            DeviceBase foldStart = Plc.deviceFoldingOperCoordMap.get(new Coord(start));
            DeviceBase foldEnd = Plc.deviceFoldingOperCoordMap.get(new Coord(end));
            switch (plcTaskType) {
                case REMOVE_PALLET:
                case ALL_OUT:
                    startStation = foldStart;
                    if (startStation == null) {
                        throw new RuntimeException("拆盘任务起始位置需要选择拆叠盘机设备");
                    }
                    break;
                case STACK_PALLET:
                case ALL_IN:
                    endStation = foldEnd;
                    if (endStation == null) {
                        throw new RuntimeException("叠盘任务终点位置需要选择拆叠盘机设备");
                    }
                    break;
                default:
                    if (foldStart != null || foldEnd != null) {
                        throw new RuntimeException("不是拆叠盘任务，起点或终点设备不能选择拆叠盘机");
                    }
                    break;
            }
        }

        if (startStation == null) {
            throw new RuntimeException("该位置未配置Plc工位设备或设备离线" + start.toString());
        }
        if (endStation == null) {
            throw new RuntimeException("该位置未配置Plc工位设备或设备离线" + end.toString());
        }

        if (startStation.getPlcDeviceType() == PlcDeviceType.CHAIN_STATION) {
            normalStationRun((StationOper) startStation, (StationOper) endStation);
        } else {
            singleConveryRun((DeviceInterface) startStation, (DeviceInterface) endStation, plcTaskType, 180);
        }
    }

    /**
     * 单体工位行驶
     * @param startDevice
     * @param endDevice
     * @param timeOut : 执行超时时间（s）
     */
    private void singleConveryRun(DeviceInterface startDevice, DeviceInterface endDevice, PlcTaskType plcTaskType,
                                  int timeOut) {
        int taskNo = ParamConfig.CONVERY_DEFAULT_TASK_ID;
        try {
            taskNo = PlcConveryTask.analyzePlcTaskNo(taskNo, plcTaskType);
            startDevice.sendConveryTask(taskNo, startDevice.getDeviceNo(), endDevice.getDeviceNo());
        } catch (IOException e) {
            throw new RuntimeException("任务下发超时");
        }

        if (endDevice.getPlcDeviceType() == PlcDeviceType.FOLDING_MACHINE) {
            while (endDevice.isRunning() || !endDevice.getTaskNo().equals(taskNo)
                    || !endDevice.getTaskEndLocation().equals(endDevice.getDeviceNo())) {
                if (endDevice.getPlcDeviceType() == PlcDeviceType.FOLDING_MACHINE) {
                    if (!(!endDevice.getTaskNo().equals(taskNo) || endDevice.isRunning()
                            || !endDevice.getTaskEndLocation().equals(endDevice.getDeviceNo()))) {
                        break;
                    }
                } else {
                    if (!(!endDevice.getTaskNo().equals(taskNo) || !endDevice.hasCargo() || endDevice.isRunning()
                            || !endDevice.getTaskEndLocation().equals(endDevice.getDeviceNo()))) {
                        break;
                    }
                }
                if (timeOut > 0) {
                    timeOut--;
                } else {
                    throw new RuntimeException("工位行驶任务执行超时:" + startDevice.getDeviceName() + " -->"
                            + endDevice.getDeviceName());
                }

                WcsFuncUtil.delay(1000);
            }
        } else {
            while (endDevice.isRunning() || !endDevice.hasCargo() || !endDevice.getTaskNo().equals(taskNo)
                    || !endDevice.getTaskEndLocation().equals(endDevice.getDeviceNo())) {
                if (timeOut > 0) {
                    timeOut--;
                } else {
                    throw new RuntimeException("工位行驶任务执行超时:" + startDevice.getDeviceName() + " -->"
                            + endDevice.getDeviceName());
                }

                WcsFuncUtil.delay(1000);
            }
        }

        try {
            endDevice.clearTaskNo();
        } catch (IOException e) {
            throw new RuntimeException("任务完成后，清除任务超时，请手动清除设备任务：" + endDevice.getDeviceName());
        }
    }

    /**
     * 普通工位行驶
     * @param startStation
     * @param endStation
     */
    private void normalStationRun(StationOper startStation, StationOper endStation) {
        int taskNo;
        // 当前位置有编号
        if (startStation.getPalletNo() != 0) {
            taskNo = startStation.getPalletNo();
        } else {
            taskNo = PlcUnit.getAutoIncrementNum();
        }

        try {
            ConveyEvent.conveyRun(null, taskNo, startStation, endStation, null);
        } catch (IOException e) {
            throw new RuntimeException("通讯失败，请确认输送线是否在线");
        }
    }

    /**
     * 查询所有已完成未上报wms的任务
     *
     * @return
     */
    @Override
    public List<TaskDB> getAllNoCommitToWmsTask() {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TaskDB::getRemark, "500").ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .isNull(TaskDB::getCommitTime);
        List<TaskDB> taskDBS = taskdbMapper.selectList(queryWrapper);
        return taskDBS;
    }

    @Override
    public List<Integer> getRgvNoByCoord(Coord coord) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.and(wrapper -> wrapper.lambda().like(TaskDB::getStartNodeStr, coord.getZ() + ")").or().like(TaskDB::getEndNodeStr, coord.getZ() + ")"));
        queryWrapper.and(wrapper -> wrapper.lambda().lt(TaskDB::getTaskStatus, TaskStatus.FINISH).isNotNull(TaskDB::getProcessingRgvNo).ne(TaskDB::getProcessingRgvNo, ""));
        queryWrapper.groupBy("processing_rgv_no");
        queryWrapper.select("distinct processing_rgv_no");
        List<TaskDB> taskDBS = taskdbMapper.selectList(queryWrapper);
        List<Integer> rgvNos = new ArrayList<>();
        for (TaskDB task : taskDBS) {
            if (!StringUtils.isEmpty(task.getProcessingRgvNo())) {
                rgvNos.add(task.getProcessingRgvNo());
            }
        }
        return rgvNos;
    }

    /**
     * 获取起点或者终点是当前层的任务分配的车辆
     * @param floor
     * @param zoneId
     * @return
     */
    @Override
    public Set<Integer> getRgvNoByFloor(Integer floor, Integer zoneId) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.and(wrapper -> wrapper.lambda().like(TaskDB::getStartNodeStr, floor + ")").or().like(TaskDB::getEndNodeStr, floor + ")"));
        queryWrapper.lambda().isNotNull(TaskDB::getPreProcessingRgvNo)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH)
                .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL);
        if (zoneId != null) {
            queryWrapper.lambda().eq(TaskDB::getZoneId, zoneId);
        } else {
            queryWrapper.lambda().isNull(TaskDB::getZoneId);
        }
        queryWrapper.groupBy("pre_processing_rgv_no");
        queryWrapper.select("distinct pre_processing_rgv_no");
        List<TaskDB> taskDBS = taskdbMapper.selectList(queryWrapper);
        Set<Integer> rgvNos = new HashSet<>();
        for (TaskDB task : taskDBS) {
            if (task != null && task.getPreProcessingRgvNo() != null) {
                rgvNos.add(task.getPreProcessingRgvNo());
            }
        }
        return rgvNos;
    }

    @Override
    public List<TaskDB> getUnFinishTaskListByFloor(int floor, Integer rgvNo) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.and(wrapper -> wrapper.lambda().like(TaskDB::getStartNodeStr, floor + ")").or().like(TaskDB::getEndNodeStr, floor + ")"));
        queryWrapper.and(wrapper -> wrapper.lambda().lt(TaskDB::getTaskStatus, TaskStatus.FINISH));
        if (rgvNo != null) {
            queryWrapper.and(wrapper -> wrapper.lambda().eq(TaskDB::getProcessingRgvNo, rgvNo).or((qw -> qw.eq(TaskDB::getPreProcessingRgvNo, rgvNo).isNull(TaskDB::getProcessingRgvNo))));
        }
        return taskdbMapper.selectList(queryWrapper);
    }

    @Override
    public List<TaskDB> getUnAssignTaskListByFloor(int floor) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.and(wrapper -> wrapper.lambda().like(TaskDB::getStartNodeStr, floor + ")").or().like(TaskDB::getEndNodeStr, floor + ")"));
        queryWrapper.lambda().eq(TaskDB::getTaskStatus, TaskStatus.NEW).isNull(TaskDB::getProcessingRgvNo).isNull(TaskDB::getPreProcessingRgvNo);
        return taskdbMapper.selectList(queryWrapper);
    }

    @Override
    public List<TaskDB> getRgvUnToStartTask(RgvDB rgvdb) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().lt(TaskDB::getRgvProgress, TaskRgvProgress.RGV_TO_START.getProgressNum())
                .lt(TaskDB::getTaskStatus, TaskStatus.FINISH)
                .eq(TaskDB::getProcessingRgvNo, rgvdb.getRgvNo());
        List<TaskDB> taskDBS = taskdbMapper.selectList(queryWrapper);
        return taskDBS;
    }

    @Override
    public void updateTaskByTaskProgrammeGridId(TaskDB taskDB, String programmeId) {
        taskDB.setTaskProgrammeGridId(programmeId);
        TaskDB currentTask = new TaskDB();
        currentTask.setTaskId(taskDB.getTaskId());
        currentTask.setTaskProgrammeGridId(programmeId);
        this.updateTaskById(currentTask);
    }

    @Override
    public void updateTaskPreProcessingRgvNo(TaskDB taskDB, Integer preProcessingRgvNo, TaskRgvProgress taskRgvProgress) {
        taskdbMapper.update(
                null,
                Wrappers.<TaskDB>lambdaUpdate()
                        .set(TaskDB::getPreProcessingRgvNo, preProcessingRgvNo)
                        .set(TaskDB::getRgvProgress, taskRgvProgress)
                        .eq(TaskDB::getTaskId, taskDB.getTaskId())
        );
        TaskDetailDB taskDetailDB = taskDetailService.getTaskDetail(taskDB.getTaskId(), DetailProcess.PRE_ASSIGN, null, null, null,
                PrecessStatus.CONDUCT, preProcessingRgvNo.toString(), null);
        taskDetailService.updateTaskDetailCompleteTime(taskDetailDB);
    }

    @Override
    public void updateTaskPreProcessingRgvNoAndProcessingRgvNo(TaskDB taskDB, Integer preProcessingRgvNo, Integer processingRgvNo, TaskRgvProgress taskRgvProgress) {
        taskdbMapper.update(
                null,
                Wrappers.<TaskDB>lambdaUpdate()
                        .set(TaskDB::getPreProcessingRgvNo, preProcessingRgvNo)
                        .set(TaskDB::getProcessingRgvNo, processingRgvNo)
                        .set(TaskDB::getRgvProgress, taskRgvProgress)
                        .eq(TaskDB::getTaskId, taskDB.getTaskId())
        );
    }

    /**
     * 更新任务执行车辆和预分配车辆，flag为true时在出库移库切换执行车辆时调用，flag为false时在重新调整任务执行车辆时调用
     *
     * @param taskDB
     * @param processingRgvNo
     * @param taskRgvProgress
     * @param flag
     * @return
     */
    @Override
    public synchronized void updateTaskProcessingRgvNoAndPreProcessingRgvNo(TaskDB taskDB, Integer processingRgvNo, TaskRgvProgress taskRgvProgress, boolean flag) {
        TaskDB currentTaskDB = this.getTaskDBById(taskDB.getTaskId());
        if (currentTaskDB == null) {
            return;
        }
        // 重新调整任务执行车辆时调用,如果执行车辆已经切换则忽略这次调整
        if (!flag && !taskDB.getProcessingRgvNo().equals(currentTaskDB.getProcessingRgvNo())) {
            return;
        }
        if (!flag) {
            TaskDetailDB taskDetailDB = taskDetailService.buildTask(taskDB.getTaskId(), DetailProcess.REST_PRE_RGV, null, null, null,
                    PrecessStatus.CONDUCT, null, null);
            taskdbMapper.update(
                    null,
                    Wrappers.<TaskDB>lambdaUpdate()
                            .set(TaskDB::getProcessingRgvNo, processingRgvNo)
                            //.set(TaskDB::getPreProcessingRgvNo, processingRgvNo)
                            //.set(TaskDB::getTaskStatus, taskProgress)
                            .set(TaskDB::getRgvProgress, taskRgvProgress)
                            .eq(TaskDB::getTaskId, taskDB.getTaskId())
            );
            taskDetailService.updateTaskDetailCompleteTime(taskDetailDB);
        } else {
            TaskDetailDB taskDetailDB = taskDetailService.getTaskDetail(taskDB.getTaskId(), DetailProcess.CHANGE_EXCUTE_RGV, null, null, null,
                    PrecessStatus.CONDUCT, processingRgvNo.toString(), null);
            taskDetailService.updateTaskDetailCompleteTime(taskDetailDB);
            taskdbMapper.updateById(taskDB);
        }
    }

    @Override
    public void updateTaskProcessingRgvNoAndPreProcessingRgvNo(TaskDB taskDB, Integer processingRgvNo, Integer preProcessingRgvNo, TaskRgvProgress taskRgvProgress) {
        taskdbMapper.update(
                null,
                Wrappers.<TaskDB>lambdaUpdate()
                        .set(TaskDB::getProcessingRgvNo, processingRgvNo)
                        .set(TaskDB::getPreProcessingRgvNo, preProcessingRgvNo)
                        .set(TaskDB::getRgvProgress, taskRgvProgress)
                        .eq(TaskDB::getTaskId, taskDB.getTaskId())
        );
        TaskDetailDB taskDetailDB = taskDetailService.getTaskDetail(taskDB.getTaskId(), DetailProcess.FORMAL_ASSIGN, null, null, null,
                PrecessStatus.CONDUCT, processingRgvNo.toString(), null);
        taskDetailDB.setDeviceInfo(processingRgvNo.toString());
        taskDetailService.updateById(taskDetailDB);
    }

    @Override
    public void updateTaskProcessingRgvNoAndPreProcessingRgvNoAndStatus(TaskDB unassignedTask, Integer processingRgvNo, Integer preProcessingRgvNo, TaskStatus wait, TaskRgvProgress assignedToRgv) {
        taskdbMapper.update(
                null,
                Wrappers.<TaskDB>lambdaUpdate()
                        .set(TaskDB::getProcessingRgvNo, processingRgvNo)
                        .set(TaskDB::getPreProcessingRgvNo, preProcessingRgvNo)
                        .set(TaskDB::getTaskStatus, wait)
                        .set(TaskDB::getRgvProgress, assignedToRgv)
                        .eq(TaskDB::getTaskId, unassignedTask.getTaskId())
        );
    }

    @Override
    public void updateTaskProcessingRgvNoAndStatus(TaskDB unassignedTask, Integer processingRgvNo, TaskStatus wait, TaskRgvProgress assignedToRgv) {
        taskdbMapper.update(
                null,
                Wrappers.<TaskDB>lambdaUpdate()
                        .set(TaskDB::getProcessingRgvNo, processingRgvNo)
                        .set(TaskDB::getTaskStatus, wait)
                        .set(TaskDB::getRgvProgress, assignedToRgv)
                        .eq(TaskDB::getTaskId, unassignedTask.getTaskId())
        );
    }

    @Override
    public List<TaskDB> findUnFinishTaskByDistrictAndRgvNOAndTaskType(int rgvNo, TaskType taskType) {
        LambdaQueryWrapper<TaskDB> lambdaQueryWrapper = new QueryWrapper<TaskDB>().lambda().eq(TaskDB::getProcessingRgvNo, rgvNo)
                .eq(TaskDB::getTaskType, taskType.getTypeNum())
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH)
                .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .orderByDesc(TaskDB::getPriorityCode).orderByAsc(TaskDB::getTaskId);
        List<TaskDB> taskdbs = taskdbMapper.selectList(lambdaQueryWrapper);
        return taskdbs;
    }


    public void updateIsAllowAssignmentRgv(TaskDB taskDB, boolean b) {
        taskDB.setAllowAssignmentRgv(b);
        TaskDB currentTask = new TaskDB();
        currentTask.setTaskId(taskDB.getTaskId());
        currentTask.setAllowAssignmentRgv(b);
        this.updateById(currentTask);
    }

    @Override
    public List<TaskDB> findTasksByGroupId(Integer taskId, String groupId, Integer type) {
        if (StringUtils.isEmpty(groupId)) {
            return null;
        }
        QueryWrapper<TaskDB> eq = new QueryWrapper<TaskDB>();
        eq.lambda().eq(TaskDB::getGroupId, groupId)
                .ge(TaskDB::getTaskId, taskId)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH);
        return getTaskDBS(type, eq);
    }

    /**
     * 根据分车情况获取任务
     * @param type
     * @param eq
     * @return
     */
    private List<TaskDB> getTaskDBS(Integer type, QueryWrapper<TaskDB> eq) {
        if (CommonUtil.PROCESSING_RGV_NO_NOT_NULL.equals(type)) {
            eq.lambda().isNotNull(TaskDB::getProcessingRgvNo);
        } else if (CommonUtil.PRE_PROCESSING_RGV_NO_NOT_NULL_PROCESSING_RGV_NO_NULL.equals(type)) {
            eq.lambda().isNotNull(TaskDB::getPreProcessingRgvNo).isNull(TaskDB::getProcessingRgvNo);
        } else if (CommonUtil.PRE_PROCESSING_RGV_NO_NULL_PROCESSING_RGV_NULL.equals(type)) {
            eq.lambda().isNull(TaskDB::getPreProcessingRgvNo).isNull(TaskDB::getProcessingRgvNo)
                    .eq(TaskDB::getAllowAssignmentRgv, true);
        }
        eq.lambda().orderByDesc(TaskDB::getPriorityCode).orderByAsc(TaskDB::getTaskId);
        List<TaskDB> newTasks = this.list(eq);
        return newTasks;
    }

    @Override
    public List<TaskDB> findTasksByGroupIdSecond(Integer taskId, String groupIdSecond) {
        if (StringUtils.isEmpty(groupIdSecond)) {
            return null;
        }
        QueryWrapper<TaskDB> eq = new QueryWrapper<TaskDB>();
        eq.lambda().eq(TaskDB::getGroupIdSecond, groupIdSecond)
                .lt(TaskDB::getTaskId, taskId)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH)
                .isNull(TaskDB::getPreProcessingRgvNo)
                .isNull(TaskDB::getProcessingRgvNo)
                .eq(TaskDB::getAllowAssignmentRgv, true);
        eq.lambda().orderByDesc(TaskDB::getPriorityCode).orderByAsc(TaskDB::getTaskId);
        List<TaskDB> newTasks = this.list(eq);
        return newTasks;
    }

    @Override
    public TaskDB findPreTaskByPreTaskId(Integer preTaskId) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TaskDB::getTaskId, preTaskId);
        TaskDB preTask = taskdbMapper.selectOne(queryWrapper);

        return preTask;
    }

    /**
     * 根据单巷道编号和与分车或重新调整类型来找任务
     *
     * @return
     */
    @Override
    public List<TaskDB> findTasksBySingleRgvFlag(String singleRgvFlag, Integer type) {
        if (StringUtils.isEmpty(singleRgvFlag)) {
            return null;
        }
        QueryWrapper<TaskDB> eq = new QueryWrapper<TaskDB>();
        eq.and(wrapper -> wrapper.lambda().eq(TaskDB::getSingleRgvFlag, singleRgvFlag).or().eq(TaskDB::getGroupIdSecond, singleRgvFlag));
        eq.lambda().ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH);
        return getTaskDBS(type, eq);
    }

    @Override
    public TaskDB findTaskByPreTaskId(Integer taskId) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TaskDB::getPreTaskId, taskId)
                .isNull(TaskDB::getProcessingRgvNo)
                .isNull(TaskDB::getPreProcessingRgvNo)
                .eq(TaskDB::getRgvProgress, TaskRgvProgress.NOT_ASSIGNED_TO_RGV)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH);
        TaskDB task = taskdbMapper.selectOne(queryWrapper);
        return task;
    }

    public boolean updateTaskTipsById(TaskDB task, String tips) {
        TaskDB currentTask = new TaskDB();
        currentTask.setTaskId(task.getTaskId());
        currentTask.setTips(tips);
        return this.updateById(currentTask);
    }

    /**
     * 查询节点内是否有任务
     * @param nodeList 一组巷道
     * @param forbidNode
     * @param rgv
     * @return
     */
    @Override
    public List<TaskDB> getTaskInRoad(List<Node> nodeList, Node forbidNode, Rgv rgv) {
        List<TaskDB> taskDBListInRoad = new ArrayList<>();
        //获取未完成的任务
        List<TaskDB> taskDBList = this.findAllUnFinishTask(null);
        NodeDBServiceImpl nodeDBService = SpringContextHolder.getBean(NodeDBServiceImpl.class);
        for (Node node : nodeList) {
            for (TaskDB taskDB : taskDBList) {
                //入库或者移库的任务 && 终点在节点集合中
                if ((TaskType.IN.equals(taskDB.getTaskType()) || TaskType.TRANSFER.equals(taskDB.getTaskType())) &&
                        node.equals(Node.parseGrid(taskDB.getEndNodeStr()))) {
                    if (isRoutForbid(WcsUtil.calcRoad(taskDB, rgv, nodeDBService), forbidNode)) {
                        taskDBListInRoad.add(taskDB);
                    }
                } else if ((TaskType.OUT.equals(taskDB.getTaskType()) || TaskType.TRANSFER.equals(taskDB.getTaskType())) &&
                        node.equals(Node.parseGrid(taskDB.getStartNodeStr()))
                        && taskDB.getRgvProgress().getProgressNum() <= TaskRgvProgress.RGV_TO_START.getProgressNum()) {
                    if (isRoutForbid(WcsUtil.calcRoad(taskDB, rgv, nodeDBService), forbidNode)) {
                        taskDBListInRoad.add(taskDB);
                    }
                }
            }
        }
        return taskDBListInRoad;
    }

    /**
     * 检测路径是否可行
     *
     * @param routes
     * @param node
     * @return
     */
    public boolean isRoutForbid(List<Route> routes, Node node) {
        if (routes == null) {
            return true;
        }
        for (Route route : routes) {
            for (Node n : route.getNodeList()) {
                if (n.equals(node)) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * 寻找未完成的出库/移库任务数
     *
     * @return
     */
    @Override
    public List<TaskDB> findUnFinishOutOrTransferTaskByStartNodeStr(String startNodeStr, Integer taskId) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TaskDB::getStartNodeStr, startNodeStr)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH)
                .in(TaskDB::getTaskType, Arrays.asList(TaskType.OUT, TaskType.TRANSFER))
                .lt(TaskDB::getTaskId, taskId);
        return this.list(queryWrapper);
    }

    /**
     * 寻找未完成的出库/移库任务数
     *
     * @return
     */
    @Override
    public List<TaskDB> findUnFinishOutOrTransferTaskByNodeStrList(Integer taskId, List<String> nodeStrList) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().in(TaskDB::getStartNodeStr, nodeStrList)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH)
                .lt(TaskDB::getTaskId, taskId)
                .in(TaskDB::getTaskType, Arrays.asList(TaskType.OUT, TaskType.TRANSFER))
                .orderByAsc(TaskDB::getTaskId);
        return this.list(queryWrapper);
    }

    /*查询节点内是否有早于该任务的入库移库任务*/
    @Override
    public List<TaskDB> getTaskInRoadLtTaskId(List<Node> nodeList, Integer taskId, Integer priorityCode) {
        List<TaskDB> taskDBListInRoad = new ArrayList<>();
        //获取未完成的任务
        List<TaskDB> taskDBList = this.findAllUnFinishTask(null);
        for (Node node : nodeList) {
            for (TaskDB taskDB : taskDBList) {
                //入库或者移库的任务 && 终点在节点集合中
                if ((TaskType.IN.equals(taskDB.getTaskType()) || TaskType.TRANSFER.equals(taskDB.getTaskType())) &&
                        node.equals(Node.parseGrid(taskDB.getEndNodeStr())) && taskDB.getTaskId() < taskId) {
                    taskDBListInRoad.add(taskDB);
                }
            }
        }
        return taskDBListInRoad;
    }

    public TaskDB findSufTaskByPreTaskId(Integer taskId) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TaskDB::getPreTaskId, taskId);
        return this.getOne(queryWrapper);
    }

    @Override
    public TaskDB getTaskDBById(Integer taSKId) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TaskDB::getTaskId, taSKId);
        return baseMapper.selectOne(queryWrapper);
    }

    /**
     * 查询某个节点位置任务所分配的车辆个数
     * @param nodeId
     * @param type
     * @return
     */
    @Override
    public Set<Integer> queryTaskByLimitRgvFlag(Integer nodeId, Integer type) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.and(wrapper -> wrapper.lambda().eq(TaskDB::getNodeLimitRgvFlag, nodeId).or().eq(TaskDB::getTransEndNodeLimitRgvFlag, nodeId));
        queryWrapper.lambda().in(TaskDB::getTaskType, Arrays.asList(TaskType.IN, TaskType.OUT, TaskType.TRANSFER))
                .isNotNull(TaskDB::getPreProcessingRgvNo)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH)
                .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL);
        queryWrapper.groupBy("pre_processing_rgv_no");
        queryWrapper.select("distinct pre_processing_rgv_no");
        List<TaskDB> taskDBS = taskdbMapper.selectList(queryWrapper);
        Set<Integer> rgvNos = new HashSet<>();
        for (TaskDB task : taskDBS) {
            if (task != null && task.getPreProcessingRgvNo() != null) {
                rgvNos.add(task.getPreProcessingRgvNo());
            }
        }
        return rgvNos;
    }

    /**
     * 更新任务终点
     *
     * @return
     */
    @Override
    public int updateTaskEndNodeStr(TaskDB taskdb, Node endNode) {
        taskdb.setEndNode(endNode);
        taskdb.setEndNodeStr(endNode.toString());
        TaskDB currentTask = new TaskDB();
        currentTask.setTaskId(taskdb.getTaskId());
        currentTask.setEndNode(endNode);
        currentTask.setEndNodeStr(endNode.toString());
        return taskdbMapper.updateById(currentTask);
    }

    @Override
    public int countExecTask(TaskType taskType) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TaskDB::getTaskType, taskType);
        queryWrapper.and(wrapper -> wrapper.lambda().eq(TaskDB::getTaskStatus, TaskStatus.ON_GOING)
                .or().eq(TaskDB::getTaskStatus, TaskStatus.COMMITTED));
        return this.count(queryWrapper);
    }

    @Override
    public int countCancelTask(TaskType taskType) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TaskDB::getTaskType, taskType).eq(TaskDB::getTaskStatus, TaskStatus.CANCEL);
        return this.count(queryWrapper);
    }

    @Override
    public int countFinishTask(TaskType taskType) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TaskDB::getTaskType, taskType).eq(TaskDB::getTaskStatus, TaskStatus.FINISH);
        return this.count(queryWrapper);
    }

    @Override
    public int countErrorTask(TaskType taskType) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TaskDB::getTaskType, taskType).eq(TaskDB::getTaskStatus, TaskStatus.ERROR);
        return this.count(queryWrapper);
    }

    @Override
    public int countWaitForExecTask(TaskType taskType) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TaskDB::getTaskType, taskType);
        queryWrapper.and(wrapper -> wrapper.lambda().ne(TaskDB::getTaskStatus, TaskStatus.ON_GOING)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH)
                .ne(TaskDB::getTaskStatus, TaskStatus.ERROR));
        return this.count(queryWrapper);
    }

    public List<TaskDB> findToRunStartInTaskByStartNodeStr(Integer taskId, String startNodeStr) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TaskDB::getStartNodeStr, startNodeStr)
                .lt(TaskDB::getRgvProgress, TaskRgvProgress.RGV_TO_END)
                .lt(TaskDB::getTaskId, taskId)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH)
                .eq(TaskDB::getTaskType, TaskType.IN);
        return this.list(queryWrapper);
    }

    /**
     * 查找该小车已生成的避让任务
     *
     * @return
     */
    @Override
    public List<TaskDB> findUnFinishAvoidTaskByEndNodeStrAndTaskType(String endNodeStr, Integer rgvNo, TaskType taskType) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TaskDB::getEndNodeStr, endNodeStr)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH)
                .eq(TaskDB::getTaskType, taskType)
                .eq(TaskDB::getProcessingRgvNo, rgvNo);
        return this.list(queryWrapper);
    }

    @Override
    public List<TaskDB> findPreProcessingTasksByRgvNo(Integer rgvNo) {
        QueryWrapper<TaskDB> eq = new QueryWrapper<>();
        eq.lambda().ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH)
                .eq(TaskDB::getPreProcessingRgvNo, rgvNo).isNull(TaskDB::getProcessingRgvNo);
        List<TaskDB> newTasks = this.list(eq);
        return newTasks;
    }

    @Override
    public List<TaskDB> queryErrorTasksByRgvNo(Integer rgvNo) {
        QueryWrapper<TaskDB> eq = new QueryWrapper<>();
        eq.lambda().ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH)
                .eq(TaskDB::getProcessingRgvNo, rgvNo)
                .orderByDesc(TaskDB::getTaskStatus);
        return this.list(eq);
    }

    @Override
    public List<Map<String, Object>> getGraphData(TaskDB taskDB) {
        List<Map<String, Object>> dataList = Lists.newArrayList();
        if (taskDB.getProcessingRgvNo() == null) {
            return dataList;
        }
        List<TaskDB> taskDBList = queryTasks(taskDB);
        Map<String, Map<String, List<TaskDB>>> sendTimeStrMap = Maps.newHashMap();
        Date sendTimeStart = (Date) taskDB.getParams().get("beginTime");
        if (CollectionUtils.isNotEmpty(taskDBList)) {
            //比较第一条任务的时间是否和开始时间一致
            //找出每天内有心跳的记录，取第一条
            for (TaskDB task : taskDBList) {
                Date createTime = task.getCreateTime();
                String sendTimeStr = DateUtil.format(createTime, DateUtil.YD);
                if (sendTimeStrMap.containsKey(sendTimeStr)) {
                    Map<String, List<TaskDB>> tasks = sendTimeStrMap.get(sendTimeStr);
                    if (TaskType.IN.equals(task.getTaskType())
                            || TaskType.OUT.equals(task.getTaskType())
                            || TaskType.TRANSFER.equals(task.getTaskType())) {
                        List<TaskDB> taskDBS = tasks.get(task.getTaskType().getDescription());
                        if (CollectionUtils.isNotEmpty(taskDBS)) {
                            taskDBS.add(task);
                        } else {
                            taskDBS.add(task);
                            tasks.put(task.getTaskType().getDescription(), taskDBS);
                        }
                    }
                } else {
                    Map<String, List<TaskDB>> tasks = Maps.newHashMap();
                    tasks.put(TaskType.IN.getDescription(), Lists.newArrayList());
                    tasks.put(TaskType.OUT.getDescription(), Lists.newArrayList());
                    tasks.put(TaskType.TRANSFER.getDescription(), Lists.newArrayList());
                    sendTimeStrMap.put(sendTimeStr, tasks);
                }
            }
        }
        fillDataList(sendTimeStart, dataList, sendTimeStrMap);
        return dataList;
    }

    @Override
    public List<TaskDB> findTasksBySingleRgvFlagAndRgvNo(TaskDB preTaskDB, Integer rgvNo) {
        if (StringUtils.isEmpty(preTaskDB.getSingleRgvFlag())) {
            return null;
        }
        QueryWrapper<TaskDB> eq = new QueryWrapper<>();
        eq.and(wrapper -> wrapper.lambda().eq(TaskDB::getSingleRgvFlag, preTaskDB.getSingleRgvFlag()).or().eq(TaskDB::getGroupIdSecond, preTaskDB.getSingleRgvFlag()));
        eq.lambda().ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH)
                .eq(TaskDB::getProcessingRgvNo, rgvNo);
        eq.lambda().gt(TaskDB::getTaskId, preTaskDB.getTaskId());
        return this.list(eq);
    }

    private void fillDataList(Date sendTimeStart, List<Map<String, Object>> dataList, Map<String, Map<String, List<TaskDB>>> sendTimeStrMap) {
        for (int i = 0; i <= INTERVAL_TIME.intValue(); i++) {
            String sendTimeStr = DateUtil.format(sendTimeStart, DateUtil.YD);
            if (sendTimeStrMap.size() > 0 && sendTimeStrMap.containsKey(sendTimeStr)) {
                addMap(sendTimeStrMap.get(sendTimeStr), dataList, sendTimeStr);
            } else {
                addMap(null, dataList, sendTimeStr);
            }
            sendTimeStart = DateUtil.addDay(1, sendTimeStart);
        }
    }

    private void addMap(Map<String, List<TaskDB>> taskMap, List<Map<String, Object>> dataList, String xValue) {
        if (taskMap != null) {
            dataList.add(fillDataMap(taskMap, xValue));
        } else {
            dataList.add(fillDataMap(null, xValue));
        }
    }

    private Map<String, Object> fillDataMap(Map<String, List<TaskDB>> taskMap, String xValue) {
        Map<String, Object> dataMap = Maps.newHashMap();
        List<Map<String, Object>> taskData = Lists.newArrayList();
        if (taskMap != null) {
            Set<String> strings = taskMap.keySet();
            strings.forEach(s -> {
                Map<String, Object> maps = Maps.newHashMap();
                maps.put("taskType", s);
                maps.put("count", taskMap.get(s).size());
                taskData.add(maps);
            });
        } else {
            List<String> stringList = Arrays.asList(TaskType.IN.getDescription(), TaskType.OUT.getDescription(), TaskType.TRANSFER.getDescription());
            stringList.forEach(s -> {
                Map<String, Object> maps = Maps.newHashMap();
                maps.put("taskType", s);
                maps.put("count", 0);
                taskData.add(maps);
            });
        }
        dataMap.put("taskData", taskData);
        dataMap.put("xValue", xValue);
        return dataMap;
    }

    @Override
    public int countTaskByEndStr(String endNodeStr) {
        QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TaskDB::getEndNodeStr, endNodeStr)
                .in(TaskDB::getTaskType, Arrays.asList(TaskType.IN, TaskType.OUT, TaskType.TRANSFER))
                .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH);

        return this.count(queryWrapper);
    }

    @Override
    public List<TaskDB> findPreProcessingTasksByRgvNoAndTaskType(Integer rgvNo, TaskType taskType) {
        QueryWrapper<TaskDB> eq = new QueryWrapper<TaskDB>();
        eq.lambda().ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.FINISH)
                .eq(TaskDB::getTaskType, taskType)
                .eq(TaskDB::getPreProcessingRgvNo,rgvNo);
        List<TaskDB> newTasks = this.list(eq);
        return newTasks;
    }

    @Override
    public List<TaskDB> findUnFinishInOrTransferByEndNode(Node node) {
            QueryWrapper<TaskDB> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(TaskDB::getEndNodeStr, node.toString())
                    .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                    .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                    .ne(TaskDB::getTaskStatus, TaskStatus.FINISH)
                    .in(TaskDB::getTaskType, Arrays.asList(TaskType.IN, TaskType.TRANSFER));
            return this.list(queryWrapper);
    }

    public TaskDB findRunForGCodeTask(int rgvNo) {
        LambdaQueryWrapper<TaskDB> eq = new QueryWrapper<TaskDB>().lambda().eq(TaskDB::getProcessingRgvNo, rgvNo)
                .eq(TaskDB::getTaskType, TaskType.RUN_FOR_GCODE)
                .ne(TaskDB::getRgvProgress, TaskRgvProgress.RGV_COMPLETE)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL).orderByDesc(TaskDB::getPriorityCode).orderByAsc(TaskDB::getTaskId);
        List<TaskDB> newTasks = this.list(eq);
        if (newTasks != null && newTasks.size() != 0) {
            return newTasks.get(0);
        }
        return null;
    }

    public void updateConnnectTaskId(Node taskEnd, Integer taskId, Integer connectTaskId) {
        TaskDB taskDB = new TaskDB();
        taskDB.setTaskId(taskId);
        taskDB.setConnectTaskId(connectTaskId);
        taskDB.setStartNode(taskEnd);
        if (taskEnd != null) {
            taskDB.setStartNodeStr(taskEnd.toString());
        }
        updateById(taskDB);
        LoggerUtil.info("更新任务信息:" + taskDB, this.getClass());
    }

    /**
     * 获取某个小车的任务状态不是：任务完成、任务完成且提交WMS、任务取消的任务
     */
    public List<TaskDB> getUnFinishTaskByRgvNo(Integer rgvNo){
        LambdaQueryWrapper<TaskDB> wrapper = new LambdaQueryWrapper<>();
        wrapper.ne(TaskDB::getTaskStatus, TaskStatus.FINISH)
                .ne(TaskDB::getTaskStatus, TaskStatus.COMMITTED)
                .ne(TaskDB::getTaskStatus, TaskStatus.CANCEL)
                .eq(TaskDB::getProcessingRgvNo, rgvNo);
        return this.list(wrapper);
    }
}
